/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package bbd.crawler.job;

import bbd.crawler.dao.ArtistDAO;
import bbd.crawler.helper.InitializeHelper;
import bbd.crawler.job.fwk.BaseJob;
import bbd.crawler.url.SimpleURLAppendHandler;
import bbd.crawler.url.URLHandlerFactory;
import bbd.crawler.url.fwk.URLHandlerInterface;
import bbd.crawler.util.Console;

import java.util.ArrayList;
import java.util.Iterator;

/**
 *
 * @author amochakr
 */
public class ArtistNamesJob extends BaseJob {

    private static final char CHAR_A = 'A';

    private static final int ALPHABETS = 1; // 26

    private ArrayList alphabets       = null;
    private ArrayList artistNames     = null;
    private ArrayList artistUrlList   = null;
    private ArrayList dbNamesList     = null;
    private ArrayList remoteNamesList = null; // copy of names list

    //--------------------------------------------------------------------------
    /** Javadoc here */
    public ArtistNamesJob ()
            throws Exception
    {
        try {

            /* change it later for database */
            //dbNamesList = new ArtistDAO().getBandArtistsNameList();
            dbNamesList = new ArrayList<String>();
            dbNamesList.add( "Dire Straits");
        }
        catch ( Exception ex ) {

            Console.error ( 
                        "ArtistNamesJob.ArtistNamesJob",
                        "(EXCEPTION) While getting artist names from DB."
                     );
            
            throw ex;
        }

        if ( dbNamesList != null ) {

            artistUrlList = new InitializeHelper().getArtistURLList();

            alphabets = new ArrayList();

            char ch = CHAR_A;

            for ( int i = 0; i < ALPHABETS; i++ ) {
                alphabets.add ( Character.toString (ch++) );
            }
        }
        else {
            
            Console.error (
                        "ArtistNamesJob.ArtistNamesJob",
                        "Artist names list from DB is NULL."
                     );

            throw new NullPointerException ( 
                            "{ArtistNamesJob} (Constructor) Names List from DB cannot be NULL"
                       );
        }

    } // end default constructor

    //--------------------------------------------------------------------------
    /** Javadoc here */
    public Object getJobOutput() {
        return artistNames;
    } // end method getJobOutput

    //--------------------------------------------------------------------------
    /** Javadoc here */
    public void execute() {

        Iterator urlIterator = artistUrlList.iterator();

        while ( urlIterator.hasNext() ) {

            try {

                String url = (String) urlIterator.next();

                URLHandlerInterface urlHandler = URLHandlerFactory.getHandlerFor (url);

                if ( urlHandler instanceof SimpleURLAppendHandler ) {
                    
                    urlHandler.init ( url, alphabets );
                }

                while ( urlHandler.hasNext() ) {

                    handleUrl ( urlHandler.getUrl() );
                }
            }
            catch (ClassNotFoundException ex) {
                Console.error ( "ArtistNamesJob.execute", ex.getMessage() );
            }
            catch (InstantiationException ex) {
                Console.error ( "ArtistNamesJob.execute", ex.getMessage() );
            }
            catch (IllegalAccessException ex) {
                Console.error ( "ArtistNamesJob.execute", ex.getMessage() );
            }
            catch (Exception ex) {
                Console.error ( "ArtistNamesJob.execute", ex.getMessage() );
                ex.printStackTrace();
            }
        }

        Console.debug ( "", "Original - " + dbNamesList.size() + " | Remote - " + remoteNamesList.size() );

        if ( remoteNamesList != null 
              && dbNamesList != null )
        {
            artistNames = getStableDelta ( remoteNamesList, dbNamesList );
        }

    } // end method execute

    //--------------------------------------------------------------------------
    /** Javadoc here */
    private ArrayList getStableDelta ( ArrayList l1, ArrayList l2) {

        ArrayList delta = new ArrayList();

        ArrayList big   = null;
        ArrayList small = null;
        ArrayList cBig  = null; // copies

        if ( l1.size() > l2.size() ) {
            big   = l1;
            small = l2;
        }
        else {
            big   = l2;
            small = l1;
        }

        big   = new ArrayList (big); // create copies of original
        small = new ArrayList (small);
        cBig  = new ArrayList (big);

        big.removeAll (small);
            
        if ( big.size() > 0 ) {
            delta.addAll (big);
        }

        small.removeAll (cBig);

        if ( small.size() > 0 ) {
            delta.addAll (small);
        }

        big    = null; // explictly set to NULL so that memory is GCed ASAP to
        small  = null; // prevent out of memory exception
        cBig   = null;

        return delta;

    } // end method getStableDelta

    //--------------------------------------------------------------------------
    /** Javadoc here */
    private void handleUrl ( String url ) throws Exception {

        ArrayList data = (ArrayList) processUrl (url);

        if ( data != null
              && data.size() > 0 )
        {
            if ( remoteNamesList == null ) {
                remoteNamesList = new ArrayList();
            }

            remoteNamesList.addAll (data);
        }

    } // end method handleUrl

} // end class ArtistNamesJob
